#include <Windows.h>
#include <tchar.h>
#include <commctrl.h>
#include "resource.h"
#pragma comment(lib, "comctl32.lib")
#pragma comment(lib, "Version.lib")

struct STreeInfo {
	HWND		hTree;
	HTREEITEM	hti;
};

BOOL CALLBACK _EnumNameProc(HMODULE hModule, LPCTSTR szType, LPTSTR szName, LONG_PTR lParam)
{
	STreeInfo* pti = (STreeInfo*)lParam;

	TVINSERTSTRUCT tvi	= {0};
	tvi.hInsertAfter	= TVI_LAST;
	tvi.hParent			= pti->hti;
	tvi.item.mask		= TVIF_TEXT|TVIF_PARAM;

	if (IS_INTRESOURCE(szName))
	{
		TCHAR szTmp[MAX_PATH];
		_stprintf(szTmp, _T("%u"), szName);
		tvi.item.pszText	= (TCHAR*)szTmp;
	} else {
		tvi.item.pszText	= (TCHAR*)szName;
	}
	tvi.item.lParam		= (LPARAM)0x1000;
	TreeView_InsertItem(pti->hTree, &tvi);

	return TRUE;
}

BOOL CALLBACK _EnumTypeProc(HMODULE hModule, LPTSTR szType, LONG_PTR lParam)
{
	STreeInfo* pti = (STreeInfo*)lParam;

	struct STypeInfo {
		LPWSTR			nID;
		const TCHAR*	szResName;
	};
	STypeInfo ResTypeList[] = { 
		{RT_CURSOR,		_T("Cursor")},		{RT_BITMAP,			_T("Bitmap")},		{RT_ICON,			_T("Icon")},
		{RT_MENU,		_T("Menu")},		{RT_DIALOG,			_T("Dialog")},		{RT_STRING,			_T("String")},
		{RT_FONTDIR,	_T("FontDir")},		{RT_FONT,			_T("Font")},		{RT_ACCELERATOR,	_T("Accelerator")},
		{RT_RCDATA,		_T("RcData")},		{RT_MESSAGETABLE,   _T("MessageTable")},{RT_GROUP_CURSOR,	_T("GroupCursor")},
		{RT_GROUP_ICON, _T("GroupIcon")},	{RT_VERSION,		_T("Version")},		{RT_DLGINCLUDE,		_T("DlgInclude")},
		{RT_PLUGPLAY,   _T("PlugPlay")},	{RT_VXD,			_T("VXD")},			{RT_ANICURSOR,		_T("AniCursor")},
		{RT_HTML,		_T("HTML")},
	};

	TVINSERTSTRUCT tvi;
	tvi.hInsertAfter	= TVI_LAST;
	tvi.hParent			= pti->hti;
	tvi.item.mask		= TVIF_TEXT|TVIF_PARAM;
	
	if (IS_INTRESOURCE(szType))
	{
		for (int ii = 0; ii < sizeof(ResTypeList)/sizeof(*ResTypeList); ii++)
		{
			if ((USHORT)ResTypeList[ii].nID == ((USHORT)szType))
			{
				tvi.item.lParam		= (LPARAM)ResTypeList[ii].nID;
				tvi.item.pszText	= (TCHAR*)ResTypeList[ii].szResName;
				HTREEITEM hti		= TreeView_InsertItem(pti->hTree, &tvi);
				STreeInfo ti		= {pti->hTree, hti};		
				EnumResourceNames(hModule, szType, _EnumNameProc, (LPARAM)&ti);	
				break;
			} 
		} 
	} else {
		tvi.item.pszText	= (TCHAR*)szType;	
		HTREEITEM hti		= TreeView_InsertItem(pti->hTree, &tvi);
		STreeInfo ti		= {pti->hTree, hti};		
		EnumResourceNames(hModule, szType, _EnumNameProc, (LPARAM)&ti);	
	}

	return TRUE;
}

HMODULE LoadModule(const TCHAR* szExePath, STreeInfo& ti)
{
	HMODULE hModule = LoadLibrary(szExePath);
	if (NULL != hModule)
	{
		EnumResourceTypes(hModule, _EnumTypeProc, (LPARAM)&ti);
		FreeLibrary(hModule);
	}

	return hModule;
}

int CALLBACK DlgProc(HWND hDlg, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	static HMODULE	hModule = NULL;
	static HWND		hTree	= NULL;
	switch (nMsg)
	{
		case WM_INITDIALOG:
		{
			SetWindowText(hDlg, _T("Demo0085"));

			UINT nWidth		= GetSystemMetrics(SM_CXSCREEN);
			UINT nHeight	= GetSystemMetrics(SM_CYSCREEN);
			RECT rtClient;
			GetClientRect(hDlg, &rtClient);
			SetWindowPos(hDlg, NULL, (nWidth - (rtClient.right - rtClient.left)) / 2, (nHeight - (rtClient.bottom - rtClient.top)) / 2, 0, 0, SWP_NOSIZE);
			
			break;
		}
		case WM_DROPFILES:
		{
			HDROP hDrop = (HDROP)wParam;
			TCHAR szPath[MAX_PATH];
			DragQueryFile(hDrop, 0, szPath, MAX_PATH);
			if (0 != _tcslen(szPath) && -1 != GetFileAttributes(szPath))
			{
				SetWindowText(GetDlgItem(hDlg, IDC_STCPATH), szPath);
				SetWindowText(GetDlgItem(hDlg, IDC_EDTINFO), _T(""));
				DragFinish(hDrop);
			}
			
			break;
		}
		case WM_NOTIFY:
		{
			NMHDR* pNMHdr = (NMHDR*)lParam;
			if (pNMHdr->code == TVN_SELCHANGED)
			{
				HTREEITEM hti = TreeView_GetSelection(hTree);
				TCHAR szName[MAX_PATH]	= {0};
				TVITEM tvi;
				tvi.mask		= TVIF_PARAM|TVIF_TEXT;
				tvi.pszText		= szName;
				tvi.hItem		= hti;
				tvi.cchTextMax	= MAX_PATH;
				TreeView_GetItem(hTree, &tvi);

				if (tvi.lParam == 0x1000)
				{
					TCHAR szType[MAX_PATH]	= {0};
					tvi.mask		= TVIF_PARAM|TVIF_TEXT;
					tvi.pszText		= szType;
					tvi.hItem		= TreeView_GetParent(hTree, hti);
					tvi.cchTextMax	= MAX_PATH;
					TreeView_GetItem(hTree, &tvi);
		
					HRSRC hRsrc = FindResource(hModule, MAKEINTRESOURCE(_ttoi(szName)), MAKEINTRESOURCE(tvi.lParam));
					if (NULL != hRsrc)
					{
						DWORD dwSize = SizeofResource(hModule, hRsrc);
						HGLOBAL hGlobal = LoadResource(hModule, hRsrc);
						LPVOID hHandle	= LockResource(hGlobal);
						switch (tvi.lParam)
						{
							case RT_ICON:
							{
								HANDLE hFile = CreateFile(_T("e:\\ResIcon.ico"), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, NULL, NULL);
								if (INVALID_HANDLE_VALUE != hFile)
								{
									DWORD dwWrited = 0;
									WriteFile(hFile, hHandle, dwSize, &dwWrited, NULL);
									CloseHandle(hFile);
								}
								
								HICON hIcon = LoadIcon(hModule, MAKEINTRESOURCE(_ttoi(szName)));
								SendDlgItemMessage(hDlg, IDC_STCICON, WM_SETICON, (WPARAM)hIcon, 0);

								break;
							}
							case RT_VERSION:
							{
								HANDLE hFile = CreateFile(_T("e:\\ResVer.txt"), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, NULL, NULL);
								if (INVALID_HANDLE_VALUE != hFile)
								{
									DWORD dwWrited = 0;
									WriteFile(hFile, hHandle, dwSize, &dwWrited, NULL);
									CloseHandle(hFile);
								}

								break;
							}
							case RT_BITMAP:
							{								
								HANDLE hFile = CreateFile(_T("e:\\ResBmp.bmp"), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, NULL, NULL);
								if (INVALID_HANDLE_VALUE != hFile)
								{
									DWORD dwWrited = 0;
									BITMAPFILEHEADER bf;
									bf.bfType	= 0x4D42;
									bf.bfOffBits= sizeof(bf) + sizeof(BITMAPINFOHEADER);
									bf.bfSize	= dwSize + sizeof(BITMAPFILEHEADER);
									WriteFile(hFile, &bf, sizeof(bf), &dwWrited, NULL);
									WriteFile(hFile, hHandle, dwSize, &dwWrited, NULL);
									CloseHandle(hFile);
								}
								break;
							}
						}
						
						UnlockResource(hGlobal);
						FreeResource(hGlobal);
					}
				}

				
			}
			break;
		}
		case WM_COMMAND:
		{
			switch (LOWORD(wParam))
			{
				case IDC_BTNVIEW:
				{
					hTree = GetDlgItem(hDlg, IDC_TREE);
					TreeView_DeleteAllItems(hTree);
					TVINSERTSTRUCT tvi	= {0};
					tvi.hParent			= NULL;
					tvi.hInsertAfter	= TVI_ROOT;
					tvi.item.mask		= TVIF_TEXT;
					tvi.item.cchTextMax	= MAX_PATH;
					tvi.item.pszText	= _T("Resources");
					HTREEITEM htiRoot	= TreeView_InsertItem(hTree, &tvi);
					STreeInfo ti		= {hTree, htiRoot};
					
					TCHAR szModule[MAX_PATH];
					GetDlgItemText(hDlg, IDC_STCPATH, szModule, MAX_PATH);
					SetWindowText(GetDlgItem(hDlg, IDC_EDTINFO), _T(""));
					hModule = LoadModule(szModule, ti);

					TreeView_Expand(hTree, htiRoot, TVM_EXPAND);

					break;
				}
				case IDC_BTNBROWSE:
				{
					TCHAR szPath[MAX_PATH] = {0};
					OPENFILENAME ofn	= {0};
					ofn.lStructSize		= sizeof(ofn);
					ofn.Flags			= OFN_EXPLORER;
					ofn.hwndOwner		= hDlg;
					ofn.lpstrFilter		= _T("execute file(*.exe)\0*.exe\0");
					ofn.nMaxFile		= MAX_PATH;
					ofn.lpstrFile		= szPath;
					if (GetOpenFileName(&ofn))
					{
						SetWindowText(GetDlgItem(hDlg, IDC_STCPATH), szPath);
					}

					break;
				}
			}
			break;
		}
		case WM_CLOSE:
		{
			PostQuitMessage(0);
			break;
		}
	}

	return 0;
}

BOOL WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPTSTR szCmdLine, int nShowCmd)
{
	InitCommonControls();

	DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG), NULL, DlgProc);

	return TRUE;
}